package com.loe.mvp.util

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Base64
import java.io.ByteArrayOutputStream
import android.annotation.SuppressLint
import android.content.ContentUris
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.util.Log
import androidx.fragment.app.FragmentActivity
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.net.URLEncoder

object FileUtil
{
    fun takeFile(activity: FragmentActivity, fileType: String, onPath: (path: String) -> Unit)
    {
        PermissionUtil.requestStorage(activity)
        {
            val intent = Intent(Intent.ACTION_GET_CONTENT)
            intent.addCategory(Intent.CATEGORY_OPENABLE)
            if (fileType.isEmpty())
            {
                intent.type = "*/*"
            } else if (fileType.contains(","))
            {
                intent.type = "*/*"
                intent.putExtra(Intent.EXTRA_MIME_TYPES, fileType.split(",").toTypedArray())
            } else
            {
                intent.type = fileType
            }
            activity.startResult(intent)
            {
                if (it.isOk() && it.data != null)
                {
                    try
                    {
                        // 相册选择
                        val uri = it.getUri()
                        // 选择返回
                        if (uri != null)
                        {
                            // 得到全路径
                            val path: String = getUriPath(activity, uri)
                            onPath(path)
                        }
                    } catch (e: Exception)
                    {
                    }
                }
            }
        }
    }

    fun takePdfFile(activity: FragmentActivity, onPath: (path: String) -> Unit)
    {
        takeFile(activity, "application/pdf", onPath)
    }

    /**
     * 文件的复制操作方法
     */
    fun copyFile(path: String?, newPath: String?): File?
    {
        val fromFile = File(path)
        val toFile = File(newPath)
        if (!fromFile.exists())
        {
            return null
        }
        if (!fromFile.isFile)
        {
            return null
        }
        if (!fromFile.canRead())
        {
            return null
        }
        if (!toFile.parentFile.exists())
        {
            toFile.parentFile.mkdirs()
        }
        if (toFile.exists())
        {
            toFile.delete()
        }
        try
        {
            val fosfrom = FileInputStream(fromFile)
            val fosto = FileOutputStream(toFile)
            val bt = ByteArray(1024)
            var c: Int
            while (fosfrom.read(bt).also { c = it } > 0)
            {
                fosto.write(bt, 0, c)
            }
            //关闭输入、输出流
            fosfrom.close()
            fosto.close()
        } catch (e: Exception)
        {
            e.printStackTrace()
        }
        return toFile
    }

    fun encodeUrl(url: String): String
    {
        // 将URL路径按文件名分隔
        val pathElements = url.split('/').toMutableList()
        // 对每个文件名部分进行编码
        for (i in pathElements.indices)
        {
            val pathElement = pathElements[i]
            if (!pathElement.contains(":"))
            {
                pathElements[i] = URLEncoder.encode(pathElement)
            }
        }
        // 将编码后的文件名部分重新组合成URL路径
        return pathElements.joinToString("/")
    }

    @SuppressLint("NewApi")
    fun getUriPath(context: Context, uri: Uri): String
    {
        val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
        val scheme = uri.scheme
        var path: String? = null

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri))
        {
            try
            {
                // ExternalStorageProvider
                if (isExternalStorageDocument(uri))
                {
                    val docId = DocumentsContract.getDocumentId(uri)
                    val split = docId.split(":").toTypedArray()
                    val type = split[0]
                    if ("primary".equals(type, ignoreCase = true))
                    {
                        path = Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                    }
                } else if (isDownloadsDocument(uri))
                {
                    val id = DocumentsContract.getDocumentId(uri)
                    val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
                    path = getDataColumn(context, contentUri, null, null)
                } else if (isMediaDocument(uri))
                {
                    val docId = DocumentsContract.getDocumentId(uri)
                    val split = docId.split(":").toTypedArray()
                    val type = split[0]
                    var contentUri: Uri? = null
                    if ("image" == type)
                    {
                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                    } else if ("video" == type)
                    {
                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                    } else if ("audio" == type)
                    {
                        contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                    }
                    val selection = "_id=?"
                    val selectionArgs = arrayOf(split[1])
                    path = getDataColumn(context, contentUri, selection, selectionArgs)
                }
            } catch (e: Exception)
            {
                Log.e("runtime", e.toString())
            }
        }
        if ("content".equals(scheme, ignoreCase = true))
        {
            try
            {
                if (isGooglePhotosUri(uri))
                {
                    return uri.lastPathSegment ?: ""
                }
                if (isQQMediaDocument(uri))
                {
                    val paths = uri.path
                    val fileDir = Environment.getExternalStorageDirectory()
                    val p = paths!!.substring(paths.indexOf("/", 1))
                    val file = File(fileDir, p)
                    path = if (file.exists()) file.toString() else null
                }
            } catch (e: Exception)
            {
                Log.e("runtime", e.toString())
            }
        }

        // MediaStore (and general)
        if (path == null)
        {
            try
            {
                path = getDataColumn(context, uri, null, null)
            } catch (e: Exception)
            {
                Log.e("runtime", e.toString())
            }
        }
        // File
        if (path == null)
        {
            try
            {
                path = uri.path
            } catch (e: Exception)
            {
                Log.e("runtime", e.toString())
            }
        }
        return path ?: ""
    }

    /****************************************************** other ******************************************************/

    private fun isQQMediaDocument(uri: Uri): Boolean
    {
        return "com.tencent.mtt.fileprovider" == uri.authority
    }

    private fun isGooglePhotosUri(uri: Uri): Boolean
    {
        return "com.google.android.apps.photos.content" == uri.authority
    }

    private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String?
    {
        var cursor: Cursor? = null
        val column = "_data"
        val projection = arrayOf(column)
        try
        {
            cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)
            if (cursor != null && cursor.moveToFirst())
            {
                val column_index = cursor.getColumnIndexOrThrow(column)
                return cursor.getString(column_index)
            }
        } finally
        {
            cursor?.close()
        }
        return null
    }

    private fun isExternalStorageDocument(uri: Uri): Boolean
    {
        return "com.android.externalstorage.documents" == uri.authority
    }

    private fun isDownloadsDocument(uri: Uri): Boolean
    {
        return "com.android.providers.downloads.documents" == uri.authority
    }

    private fun isMediaDocument(uri: Uri): Boolean
    {
        return "com.android.providers.media.documents" == uri.authority
    }

}

fun File.toCompressBase64String(limitSize: Int = 20_000): String
{
    var quality = 90
    // 加载图片为Bitmap
    val bitmapOptions = BitmapFactory.Options()
    bitmapOptions.inJustDecodeBounds = false // 我们需要解码图片
    val bitmap = BitmapFactory.decodeFile(this.absolutePath, bitmapOptions)

    // 创建一个ByteArrayOutputStream来存储压缩后的图片字节
    val byteArrayOutputStream = ByteArrayOutputStream()

    // 压缩图片到指定的字节大小以内
    var compressed = bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream)
    while (!compressed || quality > 10 && byteArrayOutputStream.size() > limitSize)
    {
        byteArrayOutputStream.reset()
        quality -= 10
        compressed = bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream)
    }

    // 将字节数组转换为Base64字符串
    val byteArray = byteArrayOutputStream.toByteArray()
    return Base64.encodeToString(byteArray, Base64.DEFAULT)
}